
package com.neotiq.smartdevice.model;

import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smackx.muc.DiscussionHistory;
import org.jivesoftware.smackx.muc.MultiUserChat;

import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ToggleButton;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

public class Device {
    
    private static final String TAG = "Device";
    
    private static String POST_HOST = "192.168.1.5";
    private static String POST_PORT = "9090";
    private static String POST_PATH = "diyse/global-repo/";
    
    private static String XMPP_HOST = "192.168.0.102";
    private static int XMPP_PORT = 5222;
    private static String XMPP_SERVICE_NAME = "192.168.0.102";
    private String XMPP_LOGIN;
    private String XMPP_PASSWORD;
    private static String XMPP_ROOM = "diyse_devices";
    
    private static XMPPConnection mXMPPConn;
    private MultiUserChat mMuc;
//    private Handler mHandler; //to listen to messages

    private DeviceType mType;

    private View mView;

    private String mName;

    private Activity delegate;

    public Device(DeviceType type, String name, Activity del) {
        super();
        delegate = del;
        mType = type;
//        mHandler = new Handler();
        switch (mType) {
            case BUTTON:
                mName = name;
//                mView = (Button)delegate.findViewById(R.id.fakeBtn);
                mView = new Button(delegate.getBaseContext());
//                mView.setVisibility(View.VISIBLE);
                ((Button)mView).setText(this.mName);
                ((Button)mView).setOnClickListener(new View.OnClickListener() {
                    
                    public void onClick(View v) {
                        Log.i(TAG, "btnClicked");
                        //buttonPressed();
                    }
                });
                this.XMPP_LOGIN = mName.replace(" ", "");
                this.XMPP_PASSWORD = "vBtn";
                break;
            case TGL_BTN:
                mName = name;
//                mView = (ToggleButton)delegate.findViewById(R.id.fakeTgl);
                mView = new ToggleButton(delegate.getBaseContext());
//                mView.setVisibility(View.VISIBLE);
                ((ToggleButton)mView).setOnClickListener(new View.OnClickListener() {
                    
                    public void onClick(View v) {
                        Log.i(TAG, "btnClicked");
                        //setState(((ToggleButton)v).isChecked());
                    }
                });
                this.XMPP_LOGIN = mName;
                this.XMPP_PASSWORD = "vTglBtn";
                break;
            default:
                break;
        }
        new Thread(new Runnable() {
			
			public void run() {
		        sendPresence();
			}
		}).start();
//        try {
//            this.initXMPPConnection();
//        } catch (XMPPException e) {
//            e.printStackTrace();
//        }
    }

    protected void buttonPressed() {
        String roomXmpp = XMPP_ROOM+"_"+XMPP_LOGIN+"_sendStatus";
        Log.i(TAG, "buttonPressed sending to room :"+roomXmpp);
        String message = "clicked";
        try {
            mMuc.sendMessage(message);
        } catch (XMPPException e) {
            e.printStackTrace();
        }
    }

    @SuppressWarnings("unused")
    private void initXMPPConnection() throws XMPPException {
        if (mXMPPConn == null || !mXMPPConn.isConnected()) {
            ConnectionConfiguration config =
                new ConnectionConfiguration(XMPP_HOST, XMPP_PORT, XMPP_SERVICE_NAME);
            mXMPPConn = new XMPPConnection(config);
            mXMPPConn.connect();
        }
        Log.i(TAG, "Login : "+this.XMPP_LOGIN+"@"+XMPP_SERVICE_NAME+" and password : "+this.XMPP_PASSWORD);
        mXMPPConn.login(this.XMPP_LOGIN+"@"+XMPP_SERVICE_NAME, this.XMPP_PASSWORD);
        Presence presence = new Presence(Presence.Type.available);
        mXMPPConn.sendPacket(presence);
        String roomXmpp = XMPP_ROOM+"_"+XMPP_LOGIN+"_sendStatus";
        mMuc = new MultiUserChat(mXMPPConn, roomXmpp+"@conference."+XMPP_SERVICE_NAME);
        DiscussionHistory history = new DiscussionHistory();
        history.setMaxStanzas(1);
        mMuc.join(XMPP_LOGIN, XMPP_PASSWORD, history, SmackConfiguration.getPacketReplyTimeout());
    }

    protected void setState(boolean checked) {
        Log.i(TAG, "setting state to :"+(checked ? "true" : "false"));
        String roomXmpp = XMPP_ROOM+"_"+XMPP_LOGIN+"_sendStatus";
        Log.i(TAG, "sending to room :"+roomXmpp);
        String message = checked ? "true" : "false";
        try {
            mMuc.sendMessage(message);
        } catch (XMPPException e) {
            e.printStackTrace();
        }
    }

    private void sendPresence() {
        DefaultHttpClient hc = new DefaultHttpClient();
        ResponseHandler<String> res = new BasicResponseHandler();
        String posturi = "http://"+POST_HOST+":"+POST_PORT+"/"+POST_PATH+XMPP_LOGIN;
        HttpPost postMethod = new HttpPost(posturi);
        postMethod.setHeader("Content-Type", "text/xml");
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();

        
        nameValuePairs.add(new BasicNameValuePair("xmlParam", this.genXML()));
        Log.i(TAG, postMethod.toString());
        StringEntity ent;
		try {
			ent = new StringEntity(this.genXML(), HTTP.UTF_8);
	        ent.setContentType("text/xml");
	        postMethod.setEntity(ent);
		} catch (UnsupportedEncodingException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
        
        Log.i(TAG, "Sending request to :"+posturi);
        
        try {
            String response = hc.execute(postMethod, res);
            Log.i(TAG, "response received :"+response);
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String genXML() {
        String ret="";
        ret += "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
        ret += "<ns2:remote-device xmlns=\"http://api.reasoning.diyse.org\" xmlns:ns2=\"http://device.diyse.org\" id=\""+XMPP_LOGIN+"\">";
        ret += "<ns2:deviceDescription type=\"virtual-device\" id=\""+XMPP_LOGIN+"\">";
        ret += "<methods name=\"switchMethod\" knowledgeLevel=\"Knowledge\" cost=\"5\"> ";
        ret += "<outputs type=\"boolean\" event=\"true\" annotation=\"Switch\" />";
        ret += "</methods>";
        ret += "</ns2:deviceDescription>";
        ret += "</ns2:remote-device>";
        return ret;
    }
    
    public void sendDelete()
    {
        DefaultHttpClient hc = new DefaultHttpClient();
        ResponseHandler<String> res = new BasicResponseHandler();
        String deluri = "http://"+POST_HOST+":"+POST_PORT+"/"+POST_PATH+XMPP_LOGIN;
        HttpDelete deleteMethod = new HttpDelete(deluri);

        Log.i(TAG, "Sending request to :"+deluri);
        
        try {
            String response = hc.execute(deleteMethod, res);
            Log.i(TAG, "response received :"+response);
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @return the mType
     */
    public DeviceType getType() {
        return mType;
    }

    /**
     * @param mType the mType to set
     */
    public void setType(DeviceType mType) {
        this.mType = mType;
    }

    /**
     * @return the mView
     */
    public View getView() {
        return mView;
    }

    /**
     * @return the mName
     */
    public String getName() {
        return mName;
    }

    /**
     * @param delegate the delegate to set
     */
    public void setDelegate(Activity delegate) {
        this.delegate = delegate;
    }
}
